package com.fkcai.hansoul.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.fkcai.hansoul.common.constant.UserConstant;
import com.fkcai.hansoul.common.util.JwtUtil;
import com.fkcai.hansoul.common.util.ResultCode;
import com.fkcai.hansoul.model.entity.User;
import com.fkcai.hansoul.mapper.UserMapper;
import com.fkcai.hansoul.model.vo.user.UserBasicVo;
import com.fkcai.hansoul.model.vo.user.UserFullVo;
import com.fkcai.hansoul.service.UserService;
import com.fkcai.hansoul.common.exception.ComFoundException;
import com.fkcai.hansoul.common.util.PasswordUtil;
import com.fkcai.hansoul.common.util.UserUtil;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Random;
import java.util.regex.Pattern;


/**
 * 实现用户业务逻辑接口的具体实现类
 */
@Service
public class UserServiceImpl implements UserService {
	@Autowired
	private UserMapper userMapper;
	
	private String[] defaultAvatars;   // 默认头像
	private String defaultCover;       // 默认封面
	
	
	/**
	 * 初始化加载用户头像和封面
	 */
	@PostConstruct
	public void init () {
		// 加载头像
		defaultAvatars = new String[] {
				"https://han-soul.oss-cn-shenzhen.aliyuncs.com/avatar/1.png",
				"https://han-soul.oss-cn-shenzhen.aliyuncs.com/avatar/2.png",
				"https://han-soul.oss-cn-shenzhen.aliyuncs.com/avatar/3.png",
				"https://han-soul.oss-cn-shenzhen.aliyuncs.com/avatar/4.png",
		};
		
		// 加载封面
		defaultCover = "https://han-soul.oss-cn-shenzhen.aliyuncs.com/cover/default_cover.png";
	}
	
	
	/**
	 * 实现注册功能
	 *
	 * @param phone    用户手机号
	 * @param password 用户密码
	 * @return 返回用户信息
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public UserBasicVo registerUser (String phone, String password) {
		// 校验手机号
		if (!Pattern.matches(UserConstant.PHONE_REGEX, phone)) {
			throw new ComFoundException(ResultCode.USER_PHONE_FORMAT_ERROR);
		}
		
		// 校验密码
		if (!Pattern.matches(UserConstant.PASSWORD_REGEX, password)) {
			throw new ComFoundException(ResultCode.USER_PASSWORD_FORMAT_ERROR);
		}
		
		User user = new User();
		user.setPhone(phone);
		// 对密码进行加密
		user.setPassword(PasswordUtil.encryptPassword(password));
		user.setUsername("han" + Math.floor(Math.random() * 10000)); // 设置默认用户名
		// 设置注册时间
		user.setRegisterTime(LocalDateTime.now());
		// 设置默认头像和封面
		user.setAvatarUrl(defaultAvatars[new Random().nextInt(4)]);
		user.setCoverUrl(defaultCover);
		
		// 插入新用户
		int result = userMapper.insert(user);
		
		if (result <= 0) {
			throw new ComFoundException(ResultCode.USER_REGISTER_ERROR);
		}
		
		// 返回用户信息
		return UserBasicVo.fromUser(user);
	}
	
	
	/**
	 * 实现用户登录功能
	 *
	 * @param phone    用户手机号
	 * @param password 用户密码
	 * @return 返回用户信息
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public UserBasicVo loginUser (String phone, String password) {
		// 校验手机号
		if (!Pattern.matches(UserConstant.PHONE_REGEX, phone)) {
			throw new ComFoundException(ResultCode.USER_PHONE_FORMAT_ERROR);
		}
		
		// 校验密码
		if (!Pattern.matches(UserConstant.PASSWORD_REGEX, password)) {
			throw new ComFoundException(ResultCode.USER_PASSWORD_FORMAT_ERROR);
		}
		
		// 查询用户是否存在
		User user = selectUserByPhone(phone);
		
		// 验证密码
		if (!PasswordUtil.checkPassword(password, user.getPassword())) {
			throw new ComFoundException(ResultCode.USER_PASSWORD_ERROR);
		}
		
		// 更新最后登陆时间
		userMapper.update(null,
				new LambdaUpdateWrapper<User>()
						.eq(User::getUserId, user.getUserId())
						.set(User::getLastLoginTime, LocalDateTime.now())
		);
		
		// 返回用户信息
		return UserBasicVo.fromUser(user);
	}
	
	
	/**
	 * 实现用户忘记密码，重置密码功能
	 *
	 * @param phone            手机号
	 * @param verificationCode 验证码
	 * @param newPassword      新密码
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public UserBasicVo forgetPassword (String phone, String verificationCode, String newPassword) {
		// 校验手机号
		if (!Pattern.matches(UserConstant.PHONE_REGEX, phone)) {
			throw new ComFoundException(ResultCode.USER_PHONE_FORMAT_ERROR);
		}
		
		// 检验验证码
		if (!"123456".equals(verificationCode)) {
			throw new ComFoundException(ResultCode.VERIFICATION_CODE_ERROR);
		}
		
		// 校验新密码
		if (!Pattern.matches(UserConstant.PASSWORD_REGEX, newPassword)) {
			throw new ComFoundException(ResultCode.USER_PASSWORD_FORMAT_ERROR);
		}
		
		// 查询用户是否存在
		User user = selectUserByPhone(phone);
		
		// 加密新密码
		String encryptedPassword = PasswordUtil.encryptPassword(newPassword);
		
		// 更新用户密码
		int updated = userMapper.update(user,
				new LambdaUpdateWrapper<User>()
						.set(User::getPassword, encryptedPassword)
						.eq(User::getPhone, phone)
						.set(User::getUpdateTime, LocalDateTime.now())
		);
		
		if (updated <= 0) throw new ComFoundException(ResultCode.USER_FORGET_PASSWORD_ERROR);
		
		return UserBasicVo.fromUser(user);
	}
	
	
	/**
	 * 实现用户修改密码功能
	 *
	 * @param phone            手机号
	 * @param oldPassword      旧密码
	 * @param verificationCode 验证码
	 * @param newPassword      新密码
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public UserBasicVo updatePassword (String phone, String oldPassword,
	                                   String verificationCode, String newPassword) {
		// 校验手机号
		if (!Pattern.matches(UserConstant.PHONE_REGEX, phone)) {
			throw new ComFoundException(ResultCode.USER_PHONE_FORMAT_ERROR);
		}
		
		// 校验当前密码和新密码格式
		if (!Pattern.matches(UserConstant.PASSWORD_REGEX, oldPassword) ||
				!Pattern.matches(UserConstant.PASSWORD_REGEX, newPassword)) {
			throw new ComFoundException(ResultCode.USER_PASSWORD_FORMAT_ERROR);
		}
		
		// 检验验证码
		if (!"123456".equals(verificationCode)) {
			throw new ComFoundException(ResultCode.VERIFICATION_CODE_ERROR);
		}
		
		// 查询用户是否存在
		User user = selectUserByPhone(phone);
		
		// 检验当前密码是否正确
		if (!PasswordUtil.checkPassword(oldPassword, user.getPassword())) {
			throw new ComFoundException(ResultCode.USER_PASSWORD_ERROR);
		}
		
		// 加密新密码
		String encryptPassword = PasswordUtil.encryptPassword(newPassword);
		
		// 更新密码
		int updated = userMapper.update(user,
				new LambdaUpdateWrapper<User>()
						.set(User::getPassword, encryptPassword)
						.eq(User::getPhone, phone)
						.set(User::getUpdateTime, LocalDateTime.now())
		);
		
		if (updated <= 0) throw new ComFoundException(ResultCode.USER_UPDATE_PASSWORD_ERROR);
		
		return UserBasicVo.fromUser(user);
	}
	
	
	/**
	 * 实现获取用户详细信息功能
	 *
	 * @param userId 用户 id
	 * @return 用户信息
	 */
	@Override
	@Transactional(readOnly = true)
	public UserFullVo getUserInfo (Integer userId) {
		// 查询用户
		User user = userMapper.selectOne(
				new LambdaQueryWrapper<User>()
						.eq(User::getUserId, userId)
		);
		
		return UserFullVo.fromUser(user);
	}
	
	
	/**
	 * 实现用户上传头像功能
	 *
	 * @param userId    用户 id
	 * @param avatarUrl 头像地址
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateUserAvatar (Integer userId, String avatarUrl) {
		int updated = userMapper.update(null,
				new LambdaUpdateWrapper<User>()
						.eq(User::getUserId, userId)
						.set(User::getAvatarUrl, avatarUrl)
						.set(User::getUpdateTime, LocalDateTime.now())
		);
		
		if (updated <= 0) throw new ComFoundException(ResultCode.FILE_UPLOAD_ERROR);
	}
	
	
	/**
	 * 实现用户上传封面功能
	 *
	 * @param userId    用户 id
	 * @param coverUrl 头像地址
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateUserCover (Integer userId, String coverUrl) {
		int updated = userMapper.update(null,
				new LambdaUpdateWrapper<User>().
						eq(User::getUserId, userId)
						.set(User::getCoverUrl, coverUrl)
						.set(User::getUpdateTime, LocalDateTime.now())
		);
		
		if (updated <= 0) throw new ComFoundException(ResultCode.FILE_UPLOAD_ERROR);
	}
	
	
	/**
	 * 实现用户更改用户名功能
	 *
	 * @param userId   用户 id
	 * @param username 用户名
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateUsername (Integer userId, String username) {
		UserUtil.filterSensitiveWords(username);    // 过滤敏感词
		
		// 查询用户信息
		User user = userMapper.selectOne(
				new LambdaQueryWrapper<User>().eq(User::getUserId, userId)
		);
		
		if (user == null) {
			throw new ComFoundException(ResultCode.USER_NOT_EXIST);
		}
		
		// 判断修改后的昵称是否一致
		if (username.equals(user.getUsername())) throw new ComFoundException(ResultCode.USERNAME_DUPLICATED);
		
		// 判断在 7 内是否修改过昵称
		UserUtil.checkUsernameUpdateInterval(user.getLastUsernameUpdateTime());
		
		int updated = userMapper.update(null,
				new LambdaUpdateWrapper<User>()
						.eq(User::getUserId, userId)
						.set(User::getUsername, username)
						.set(User::getUpdateTime, LocalDateTime.now())
						.set(User::getLastUsernameUpdateTime, LocalDateTime.now())
		);
		
		if (updated <= 0) throw new ComFoundException(ResultCode.USERNAME_UPDATE_ERROR);
	}
	
	
	/**
	 * 实现用户性别更改
	 *
	 * @param userId 用户 id
	 * @param gender 用户 性别
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateGender (Integer userId, String gender) {
		if (!Arrays.asList("男", "女", "保密").contains(gender)) {
			throw new ComFoundException(ResultCode.USER_GENDER_NOT_EXIST);
		}
		
		int updated = userMapper.update(null,
				new LambdaUpdateWrapper<User>()
						.eq(User::getUserId, userId)
						.set(User::getGender, gender)
						.set(User::getUpdateTime, LocalDateTime.now())
		);
		
		if (updated <= 0) throw new ComFoundException(ResultCode.USER_GENDER_UPDATE_ERROR);
	}
	
	
	/**
	 * 实现用户生日，年龄更改
	 *
	 * @param userId   用户 id
	 * @param birthday 用户生日
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateBirthday (Integer userId, LocalDate birthday) {
		int updated = userMapper.update(null,
				new LambdaUpdateWrapper<User>()
						.eq(User::getUserId, userId)
						.set(User::getBirthday, birthday)
						.set(User::getUpdateTime, LocalDateTime.now())
		);
		
		if (updated <= 0) throw new ComFoundException(ResultCode.USER_BIRTHDAY_UPDATE_ERROR);
	}
	
	
	/**
	 * 实现用户地区修改
	 *
	 * @param userId   用户 id
	 * @param location 用户地区
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateLocation (Integer userId, String location) {
		int updated = userMapper.update(null,
				new LambdaUpdateWrapper<User>()
						.eq(User::getUserId, userId)
						.set(User::getLocation, location)
						.set(User::getUpdateTime, LocalDateTime.now())
		);
		
		if (updated <= 0) throw new ComFoundException(ResultCode.USER_LOCATION_UPDATE_ERROR);
	}
	
	
	/**
	 * 实现用户简介更改
	 *
	 * @param userId 用户 id
	 * @param bio    用户简介
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateBio (Integer userId, String bio) {
		String filteredBio = UserUtil.replaceSensitiveWords(bio);    // 敏感词过滤并替换为 **
		
		if (filteredBio.length() > UserConstant.USER_BIO_MAX_LENGTH) {
			throw new ComFoundException(ResultCode.USER_BIO_TOO_LONG);
		}
		
		int updated = userMapper.update(null,
				new LambdaUpdateWrapper<User>()
						.eq(User::getUserId, userId)
						.set(User::getBio, filteredBio)
						.set(User::getUpdateTime, LocalDateTime.now())
		);
		
		if (updated <= 0) throw new ComFoundException(ResultCode.USER_BIO_UPDATE_ERROR);
	}
	
	
	/**
	 * 根据手机号查询用户
	 *
	 * @param phone 手机号
	 * @return 用户信息
	 */
	public User selectUserByPhone (String phone) {
		// 查询用户
		User user = userMapper.selectOne(
				new LambdaQueryWrapper<User>()
						.eq(User::getPhone, phone)
		);
		
		// 判断用户是否存在
		if (user == null) {
			throw new ComFoundException(ResultCode.USER_NOT_EXIST);
		}
		
		return user;
	}
	
	
}
